import Main from "../main"
import {Edge, Node} from "pack-antv-x6"
import {h} from "vue"
import Contextmenu from "../components/contextmenu.vue"
import { sum } from "lodash-es"
import {useDebounceFn} from "@vueuse/core"
import {NODE_WIDTH,LINE_HEIGHT,NODE_HEIGHT} from "../markup/node"

export default (main:Main) => {
    main.graph.onMounted((graph) => {
        // 右键菜单
        graph.on("cell:contextmenu",({cell,e}) => {
            if(main.graph.mode.value == 'prod') return ;
            if(cell.isEdge() && cell.prop('nodeedge') == true){ return ;}
            // @ts-ignore
            main.contextmenu.open(e,h(Contextmenu,{main,cell}))
        })
        // 初始化加载时节点需要初始化状态
        graph.on('render:done',() => {
            const nodes = graph.getNodes();
            for(const node of nodes){
                // node.prop({ collapse: false })
                node.prop({isInputInit:false})
                nodeInit(node);
                // nodeCollapse(node,false)
                // nodeSearch(node,'')
            }
            // const edges = graph.getEdges();
            // for(const edge of edges){
            //     edgeAdded(edge)
            // }
        })
        // 节点新增
        graph.on("node:added",({node}) => {nodeAdded(node)})
        // 边的连接建立
        graph.on("edge:connected",({edge}) => {
            if(edge.prop('nodeedge') == true) return ;
            edgeAdded(edge)
        })
        // 搜索
        graph.on("node:search",({e,node}:{e:MouseEvent,node:Node}) => {
            
            const isInputInit = node.prop('isInputInit')
            const collapse = node.prop('collapse')
            if(collapse == true){
                nodeCollapse(node,false)
            }
            //
            // console.log('node:search ==>',isInputInit,collapse)
            if(isInputInit != true){
                e.target?.addEventListener('input', (evt: any) => {
                    // console.log('input =========>')
                    const s = evt.target.value;
                    nodeSearch(node,s)
                })
                node.prop({isInputInit:true})
            }
        })
        // 折叠与展开
        graph.on('node:collapse',({node}:{node:Node}) => {
            nodeCollapse(node)
        })
    })

    const nodeAdded = (node:Node) => {
        if(node.shape == 'er-node'){
            node.prop({collapse:false})
            const stroke = node.prop('stroke');
            if(stroke){
                node.getPorts().forEach((port:any) => { 
                    node.portProp(port.id,'attrs/left/stroke',stroke)
                    node.portProp(port.id,'attrs/right/stroke',stroke)
                  })
            }
            const ports = node.getPorts();
            // const size = node.size();
            node.setData({ports})
            // console.log(node.size(),ports)
            node.resize(NODE_WIDTH,NODE_HEIGHT + ports.length * LINE_HEIGHT + 2)
        }
        
    }

    const edgeAdded = (edge:Edge) => {
        edge.prop({portedge:true})
        // 获取所有的 ports 边数据
        const sn = edge.getSourceCell() as Node;
        const tn = edge.getTargetCell() as Node;
        //
        const edges = getAllPortsEdge(sn,tn)
        // 判定是否存在特殊边
        const e = getSpecialEdge(sn,tn);
        //
        if(e == undefined){
            main.graph.addEdge({
                shape:'edge',
                source:{cell:sn.id,selector:"edgePort",anchor:{name:"midSide",args:{direction:"H"}}},
                target:{cell:tn.id,selector:"edgePort",anchor:{name:"midSide",args:{direction:"H"}}},
                zIndex:1,
                nodeedge:true,
                data:{edges},
                router: {
                    name: 'er',
                  args: {
                    offset: 15,
                    direction: 'H',
                  },
                },
                attrs:{
                    line:{
                        stroke:"#5C89AC" 
                    }
                }
            })
        }
        else {
            e.setData(edges)
        }

    }

    const nodeCollapse = (node:Node,bool?:boolean,slient = false) => {
        const v = node.prop('collapse');
        const val = bool == undefined ? !v : bool;
        node.prop({ collapse: val })
        const {ports} = node.getData();
        // 折叠
        if(val === true){
            node.removePorts(ports)
            node.resize(NODE_WIDTH, NODE_HEIGHT)
        }
        else { // 展开
            node.removePorts()
            node.addPorts(ports);
            !slient && recoverPortsEdge(node);
            // node.resize(size.width, size.height + ports.length * 16 + 2)
            node.resize(NODE_WIDTH,NODE_HEIGHT + ports.length * LINE_HEIGHT + 2)
        }
    }

    const nodeSearch = useDebounceFn((node:Node,s:string) => {
        const {ports} = node.getData()
        const ps = ports.filter((p:any) => {
            const ts = Object.keys(p.attrs).map(k => p.attrs[k].text).filter(t => !!t);
            return sum(ts.map(t => new RegExp(s,'i').test(t) ? 1 : 0)) > 0
        })
        //
        node.removePorts();
        node.addPorts(ps);
        // node.resize(size.width, size.height + ps.length * 16 + 2)
        node.resize(NODE_WIDTH,NODE_HEIGHT + ps.length * LINE_HEIGHT + 2)
        setTimeout(() => {
            recoverPortEdge(node,ps)
        },30)
    },200)


    const nodeInit = (node:Node) => {
        const b = node.prop('collapse');
        if(b){
            return ;
        }
        const {ports} = node.getData()
        node.removePorts();
        node.addPorts(ports);
        recoverPortsEdge(node);
        node.resize(NODE_WIDTH,NODE_HEIGHT + ports.length * LINE_HEIGHT + 2)
    }


    const recoverPortEdge = (node:Node,ports:any[]) => {
        const es = getAllSpecialEdges(node);
        const pids = ports.map(p => p.id)
        for(const e of es){
            const {edges} = e.getData();
            const ess = edges.filter((e:any) => pids.includes(e.source.port) || pids.includes(e.target.port))
            main.graph.addEdges(ess)
        }
    }

    const recoverPortsEdge = useDebounceFn((node:Node) => {
        const es = getAllSpecialEdges(node);
        for(const e of es){
            recoverEdge(e)
        }
    },30)
    // 依据节点的边恢复 port 边 会检测两个节点的状态
    const recoverEdge = (edge:Edge) => {
        const sn = edge.getSourceCell();
        const tn = edge.getTargetCell();
        //
        const st = sn?.prop('collapse');
        const tt = tn?.prop('collapse');
        //
        if(st == false && tt == false){
            const {edges} = edge.getData();
            main.graph.addEdges(edges)
        }
    }

    const getAllSpecialEdges = (node:Node) => {
        const es = main.graph.getEdges().filter(e => (e.getSourceCell() == node || e.getTargetCell() == node) && e.prop('nodeedge') == true);
        return es;
    }

    const getSpecialEdge = (sourceNode:Node,targetNode:Node) => {
        const es = main.graph.getEdges().filter(e => e.getSourceCell() == sourceNode && e.getTargetCell() == targetNode && e.prop('nodeedge') == true)
        return es[0]
    }

    const getAllPortsEdge = (sourceNode:Node,targetNode:Node) => {
        const es = main.graph.getEdges().filter(e => e.getSourceCell() == sourceNode && e.getTargetCell() == targetNode && e.prop('portedge') == true);
        return es.map(e => e.toJSON())
    }

    return {
        recoverPortsEdge,
        getAllSpecialEdges,
        getSpecialEdge,
        getAllPortsEdge,
    }
}